
import * as sqlite3 from 'sqlite3';
import { Database } from './database';
import { Interface, Project } from './interface';
import { getId } from './utils';

export class Service {

  database: sqlite3.Database | undefined;

  constructor() {
    this.database = Database.getSingle().database;
  }

  public addProject(project: Project): Promise<void> {
    return new Promise(resolve => {
      const id = getId();
      this.database?.run("insert into project(id, name, code) values(?,?,?)", [id, project.name, project.code], (e: any) => {
        if (!e) {
          resolve();
        }
      });
    });
  }

  public queryProjects(): Promise<Project[]> {
    return new Promise(resolve => {
      this.database?.all("select * from project", (e: any, data: Project[]) => {
        if (!e) {
          resolve(data);
        }
      });
    });
  }

  public addInterface(api: Interface): Promise<void> {
    return new Promise(resolve => {
      const id = getId();
      const sql = `insert into 
      interface(id, name, desc, project_id, method, url, data_type, array_max_length, array_min_length, delay) 
      values(?,?,?,?,?,?,?,?,?,?);`;
      const stmt = this.database?.prepare('insert into response_field(id, name, type, desc, interface_id, setting) values(?,?,?,?,?,?)');
      this.database?.run(sql,
        [id, api.name, api.desc, api.projectId, api.method, api.url, api.dataType, api.arrayMaxLength, api.arrayMinLength, api.delay],
        (e: any) => {
          if (!e) {
            (api.fields || []).forEach(field => {
              const fieldId = getId();
              stmt?.run([fieldId, field.name, field.type, field.desc, id, field.setting ? JSON.stringify(field.setting) : '{}']);
            });
            stmt?.finalize((error) => {
              if (!error) {
                resolve();
              } else {
                console.log(error);
              }
            });
          } else {
            console.log(e);
          }
        });
    });
  }

  public queryInterfaces(id: string): Promise<Interface[]> {
    return new Promise(resolve => {
      this.database?.all("select * from interface where project_id = ?", [id], (e: any, data: Interface[]) => {
        if (!e) {
          resolve(data);
        }
      });
    });
  }

  public queryInterface(id: string): Promise<any> {

    return new Promise(resolve => {
      const sql = `SELECT
      i.url AS url,
      p.code AS projectCode 
    FROM
      interface AS i
      LEFT JOIN project AS p ON i.project_id = p.id 
    WHERE
      i.id = ?`;
      this.database?.all(sql, [id], (e: any, data: Interface[]) => {
        if (!e && data.length) {
          resolve(data[0]);
        } else {
          resolve({});
        }
      });
    });
  }

  public queryInterfaceByUrl(projectCode: string, url: string): Promise<any> {
    return new Promise(resolve => {
      let sql = `SELECT
      i.id as interfaceId, 
      i.name as interfaceName,
      i.data_type as dataType,
      i.array_max_length as arrayMaxLength,
      i.array_min_length as arrayMinLength,
      i.delay as delay
    FROM
      interface AS i
      LEFT JOIN project AS p ON i.project_id = p.id 
    WHERE
      i.url = ? 
      AND p.code = ?`;
      this.database?.all(sql, [url, projectCode], (e: any, data: any) => {
        if (!e) {
          if (data.length) {
            sql = `SELECT
            * 
          FROM
            response_field AS p
          WHERE
            p.interface_id = ?`;
            this.database?.all(sql, [data[0].interfaceId], ((error: any, fields: any) => {
              if (!error) {
                resolve({
                  ...data[0],
                  fields,
                });
              } else {
                console.log(error);
              }
            }));
          } else {
            console.log(e);
            resolve(data);
          }
        }
      });
    });
  }

}